package design.donkey.auto.ddl.analysis;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import design.donkey.auto.ddl.model.ColumnMetaModel;
import design.donkey.auto.ddl.model.IndexMetaModel;
import design.donkey.framework.common.orm.annotation.PrimaryKeyType;
import design.donkey.framework.common.util.CommonUtils;
import jakarta.persistence.*;
import lombok.extern.slf4j.Slf4j;

/**
 * JpaAnnotationAnalysis
 *
 * @author zhangjiakung
 * @since 0.0.1
 */
@Slf4j
public class JpaAnnotationAnalysis extends AnnotationAnalysis {

    @Override
    public boolean isDomain(Class<?> domainClazz) {
        return super.isDomain(domainClazz) || domainClazz.getAnnotation(Table.class) != null
            || domainClazz.getAnnotation(Entity.class) != null;
    }

    @Override
    protected String getTableCatalog(Class<?> domainClazz) {
        Table tableAnnotation = domainClazz.getAnnotation(Table.class);
        return get(tableAnnotation == null ? null : tableAnnotation.catalog())
            .orElseGet(() -> super.getTableCatalog(domainClazz));
    }

    @Override
    protected String getTableSchema(Class<?> domainClazz) {
        Table tableAnnotation = domainClazz.getAnnotation(Table.class);
        return get(tableAnnotation == null ? null : tableAnnotation.schema())
            .orElseGet(() -> super.getTableSchema(domainClazz));
    }

    @Override
    protected String getTableName(Class<?> domainClazz) {
        Table tableAnnotation = domainClazz.getAnnotation(Table.class);
        return get(tableAnnotation == null ? null : tableAnnotation.name())
            .orElseGet(() -> super.getTableName(domainClazz));
    }

    @Override
    protected List<IndexMetaModel> getIndexes(Class<?> domainClazz) {
        // 自定义注解索引
        List<IndexMetaModel> resultList = super.getIndexes(domainClazz);
        // jpa 索引
        Table tableAnnotation = domainClazz.getAnnotation(Table.class);
        // 索引
        if (tableAnnotation != null && CommonUtils.isNotEmpty(tableAnnotation.indexes())) {
            Index[] indexes = tableAnnotation.indexes();
            for (Index index : indexes) {
                IndexMetaModel indexMetaModel = new IndexMetaModel();
                indexMetaModel.setName(index.name());
                indexMetaModel.setColumnNames(Arrays.stream(index.columnList().split(",")).map(String::trim)
                    .filter(CommonUtils::isNotBlank).toArray(String[]::new));
                indexMetaModel.setUnique(index.unique());
                indexMetaModel.setPrimaryKey(false);
                resultList.add(indexMetaModel);
            }
        }
        // 唯一索引
        if (tableAnnotation != null && CommonUtils.isNotEmpty(tableAnnotation.uniqueConstraints())) {
            UniqueConstraint[] indexes = tableAnnotation.uniqueConstraints();
            for (UniqueConstraint index : indexes) {
                IndexMetaModel indexMetaModel = new IndexMetaModel();
                indexMetaModel.setName(index.name());
                indexMetaModel.setColumnNames(index.columnNames());
                indexMetaModel.setUnique(true);
                indexMetaModel.setPrimaryKey(false);
                resultList.add(indexMetaModel);
            }
        }
        return resultList;
    }

    @Override
    protected List<ColumnMetaModel> getColumns(ModelField field) {
        // 支持jpa Transient 注解
        Transient transientAnnotation = field.getAnnotation(Transient.class);
        if (transientAnnotation != null) {
            return Collections.emptyList();
        }
        return super.getColumns(field);
    }

    @Override
    protected String getColumnName(ModelField field) {
        Column columnAnnotation = field.getAnnotation(Column.class);
        return get(columnAnnotation == null ? null : columnAnnotation.name())
            .orElseGet(() -> super.getColumnName(field));
    }

    @Override
    protected int getColumnLength(ModelField field) {
        // 用户自定义了 字段类型
        Column columnAnnotation = field.getAnnotation(Column.class);
        if (columnAnnotation != null) {
            return columnAnnotation.length();
        }
        return super.getColumnLength(field);
    }

    @Override
    protected int getColumnPrecision(ModelField field) {
        // 用户自定义了 字段类型
        Column columnAnnotation = field.getAnnotation(Column.class);
        if (columnAnnotation != null) {
            return columnAnnotation.precision();
        }
        return super.getColumnPrecision(field);
    }

    @Override
    protected int getColumnScale(ModelField field) {
        // 用户自定义了 字段类型
        Column columnAnnotation = field.getAnnotation(Column.class);
        if (columnAnnotation != null) {
            return columnAnnotation.scale();
        }
        return super.getColumnScale(field);
    }

    @Override
    protected boolean getColumnNullable(ModelField field) {
        // 用户自定义了 字段类型
        Column columnAnnotation = field.getAnnotation(Column.class);
        if (columnAnnotation != null) {
            return columnAnnotation.nullable();
        }
        return super.getColumnNullable(field);
    }

    @Override
    protected String getColumnDefinition(ModelField field) {
        // 用户自定义了 字段类型
        Column columnAnnotation = field.getAnnotation(Column.class);
        if (columnAnnotation != null) {
            return columnAnnotation.columnDefinition();
        }
        return super.getColumnDefinition(field);
    }

    @Override
    protected boolean getColumnPrimaryKey(ModelField field) {
        // 用户自定义了 字段类型
        Id idAnnotation = field.getAnnotation(Id.class);
        if (idAnnotation != null) {
            return true;
        }
        return super.getColumnPrimaryKey(field);
    }

    @Override
    protected PrimaryKeyType getColumnPrimaryKeyType(ModelField field) {
        // 用户自定义了 字段类型
        GeneratedValue generatedValueAnnotation = field.getAnnotation(GeneratedValue.class);
        if (generatedValueAnnotation != null) {
            GenerationType strategy = generatedValueAnnotation.strategy();
            if (GenerationType.IDENTITY.equals(strategy)) {
                return PrimaryKeyType.JDBC;
            }
            if (GenerationType.AUTO.equals(strategy)
                && PrimaryKeyType.JDBC.name().equalsIgnoreCase(generatedValueAnnotation.generator())) {
                return PrimaryKeyType.JDBC;
            }
            return PrimaryKeyType.SOFT;
        }
        return super.getColumnPrimaryKeyType(field);
    }

    @Override
    protected boolean getColumnUnique(ModelField field) {
        // 用户自定义了 字段类型
        Column columnAnnotation = field.getAnnotation(Column.class);
        if (columnAnnotation != null) {
            return columnAnnotation.unique();
        }
        return super.getColumnUnique(field);
    }
}
